package dk.itu.KrakMap;

/**
 * Represents a point on a map, denoted by its UTM-32 coordintes. Also provides
 * varoius functions for calculating relevant values regarding to one or more
 * MapPoints.
 * @author ITU-KF04-2011, Group 11
 */
public class MapPoint {

    private double x;
    private double y;

    /**
     * Construct a MapPoint from UTM-32 coordinates
     * @param x UTM-32 x-coordinate
     * @param y UTM-32 y-coordinate
     */
    public MapPoint(double x, double y) {
        this.x = x;
        this.y = y;
    }

    /**
     * Get the x coordinate
     * @return The UTM-32 x-coordinate
     */
    public double getX() {
        return x;
    }

    /**
     * Get the y coordinate
     * @return The UTM-32 y-coordinate
     */
    public double getY() {
        return y;
    }

    /**
     * Move the MapPoint by the given values, where positive values means move
     * up and right.
     * @param x How much to move the MapPoint along x-axis, eg. right
     * @param y How much to move the MapPoint along y-axis, eg. up
     */
    public void move(double x, double y) {
        this.setX(this.x + x);
        this.setY(this.y + y);
    }

    /**
     * Set the x-coordinate of the MapPoint
     * @param x UTM-32 x-coordinate
     */
    public void setX(double x) {
        this.x = x;
    }

    /**
     * Set the y-coordinate of the MapPoint
     * @param y UTM-32 y-coordinate
     */
    public void setY(double y) {
        this.y = y;
    }

    /**
     * Get the distance between this MapPoint and one other MapPoint
     * @param point The MapPoint to calculate the distance to.
     * @return The distance in meters
     */
    public double dist(MapPoint point) {
        return MapPoint.dist(this, point);
    }

    /**
     * Get the distance between two MapPoints
     * @param a The one MapPoint
     * @param b The other MapPoint
     * @return The distance in meters.
     */
    public static double dist(MapPoint a, MapPoint b) {
        double distA = Math.abs(a.getX() - b.getX());
        double distB = Math.abs(a.getY() - b.getY());
        return Math.sqrt(distA * distA + distB * distB);
    }

    @Override
    public MapPoint clone() {
        return new MapPoint(getX(), getY());
    }

    /**
     * Two MapPoints are equal if an only if both of their x and y coordinates
     * are respectively equal to each other.
     * @param obj The object to compare
     * @return true if the two objects are equal, false if not
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof MapPoint) {
            MapPoint point = (MapPoint) obj;
            return getX() == point.getX() && getY() == point.getY();
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 61 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
        hash = 61 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
        return hash;
    }

    @Override
    public String toString()
    {
        return "("+getX()+";"+getY()+")";
    }
}
